package com.example.listener;


import com.example.bean.User;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.*;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Session监听器 - 限制一个用户同一时间只能登录一次
 */
@WebListener
public class SessionListener implements HttpSessionListener, HttpSessionAttributeListener {

    // 存储用户名和对应的session映射关系
    // key: username, value: HttpSession
    private static final Map<String, HttpSession> USER_SESSION_MAP = new ConcurrentHashMap<>();

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("Session created: " + se.getSession().getId());
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        HttpSession session = se.getSession();
        System.out.println("Session destroyed: " + session.getId());

        // 从映射中移除该session对应的用户
        User user = (User) session.getAttribute("currentUser");
        if (user != null) {
            String username = user.getUsername();
            // 只有当映射中的session与当前销毁的session相同时才移除
            USER_SESSION_MAP.remove(username, session);
            System.out.println("User " + username + " session removed from map");
        }
    }

    @Override
    public void attributeAdded(HttpSessionBindingEvent se) {
        String attributeName = se.getName();

        // 当添加currentUser属性时（即用户登录时）
        if ("currentUser".equals(attributeName)) {
            User user = (User) se.getValue();
            String username = user.getUsername();
            HttpSession newSession = se.getSession();

            System.out.println("User " + username + " logged in, session: " + newSession.getId());

            // 检查该用户是否已经在其他地方登录
            HttpSession oldSession = USER_SESSION_MAP.get(username);

            if (oldSession != null && !oldSession.getId().equals(newSession.getId())) {
                // 如果存在旧的session，使其失效
                try {
                    System.out.println("Invalidating old session for user: " + username + ", old session: " + oldSession.getId());

                    // 在旧session中设置一个标记，表示被踢出
                    oldSession.setAttribute("kickedOut", true);
                    oldSession.setAttribute("kickMessage", "您的账号在其他地方登录，当前会话已失效！");

                    // 使旧session失效
                    oldSession.invalidate();
                } catch (IllegalStateException e) {
                    // session可能已经失效，忽略异常
                    System.out.println("Old session already invalidated: " + e.getMessage());
                }
            }

            // 将新的session存入映射
            USER_SESSION_MAP.put(username, newSession);
            System.out.println("Current online users: " + USER_SESSION_MAP.keySet());
        }
    }

    @Override
    public void attributeRemoved(HttpSessionBindingEvent se) {
        String attributeName = se.getName();

        // 当移除currentUser属性时（即用户登出时）
        if ("currentUser".equals(attributeName)) {
            User user = (User) se.getValue();
            if (user != null) {
                String username = user.getUsername();
                HttpSession session = se.getSession();

                // 只有当映射中的session与当前session相同时才移除
                USER_SESSION_MAP.remove(username, session);
                System.out.println("User " + username + " logged out");
            }
        }
    }

    @Override
    public void attributeReplaced(HttpSessionBindingEvent se) {
        // 属性被替换时的处理（一般不需要特殊处理）
    }

    /**
     * 获取当前在线用户数
     */
    public static int getOnlineUserCount() {
        return USER_SESSION_MAP.size();
    }

    /**
     * 获取所有在线用户
     */
    public static Map<String, HttpSession> getOnlineUsers() {
        return USER_SESSION_MAP;
    }
}

